`include "defines.v"
`define State_Free 2'b00
`define State_End 2'b01
`define State_On 2'b10
`define State_ByZero 2'b11

module div(
	input wire rst,
	input wire clk,
	input wire[31:0] data1_i, //被除数
	input wire[31:0] data2_i, //除数
	input wire signed_i, //是否为带符号除法(1:带符号)
	input wire start_i, //开始信号
	input wire cancel_i, //取消信号
	output reg[63:0] result_o, //结果
	output reg finish_o //是否运算完成
);
	reg[1:0] state;
	reg[5:0] count; //运算次数
	reg[63:0] temp_div_result; //临时除法结果，运算开始后，
	//[k:0]位为k次迭代完成后商的结果，[62:31]位为每次运算的被减数
	//[30:k+1]位为被除数中未参与运算的数据
	//经过32次运算后，[63:32]位为余数， [31:0]为商
	wire[32:0] sub_result; //每次减法运算的结果，sub_result[32]为符号位
	reg[31:0] subtractor; //被减数		

	assign sub_result = {1'b0, temp_div_result[62:31]} - {1'b0, subtractor};

	always@(posedge clk)
		if(rst == `RstEnable)
		begin
			state <= `State_Free;
			result_o <= {`ZeroWord, `ZeroWord};
			finish_o <= `DivNoFinish;
		end
		else
			case(state)
			`State_Free:
			begin
				if(start_i == `DivStart && cancel_i == `DivNoCancel && data2_i == `ZeroWord)
					state <= `State_ByZero;
				else if(start_i == `DivStart && cancel_i == `DivNoCancel && data2_i != `ZeroWord)
				begin
					count <= 0;
					state <= `State_On;
					if(signed_i == 1'b1 && data2_i[31] == 1'b1)
						subtractor <= ~data2_i + 1;
					else
						subtractor <= data2_i;
					if(signed_i == 1'b1 && data1_i[31] == 1'b1)
						temp_div_result <= {32'b0, (~data1_i + 1)};
					else 
						temp_div_result <= {32'b0, data1_i};
				end
				else 
				begin
					state <= `State_Free;
					result_o <= {`ZeroWord, `ZeroWord};
					// finish_o <= `DivNoFinish;
				end
			end
			`State_ByZero:
			begin
				state <= `State_End;
				temp_div_result <= {`ZeroWord, `ZeroWord};
			end
			`State_End:
			begin
				result_o <= temp_div_result;
				finish_o <= 1'b1;
				if(start_i == `DivStop)
				begin
					state <= `State_Free;
					finish_o <= 1'b0;
					result_o <= {`ZeroWord, `ZeroWord};
				end
			end				
			`State_On:
				if(cancel_i == `DivCancel)
					state <= `State_Free;
				else if(count[5] == 1'b1)
				begin
					if(signed_i == 1'b1 && (data1_i[31] != data2_i[31]))
						temp_div_result[31:0] <= ~temp_div_result[31:0] + 1;
					if(signed_i == 1'b1 && data1_i[31] == 1'b1) //余数与被除数符号相同
						temp_div_result[63:32] <= ~temp_div_result[63:32] + 1;
					state <= `State_End;
					// count <= 0;
				end
				else
				begin
					if(sub_result[32] == 1'b1) //被减数小于减数
						temp_div_result <= {temp_div_result[62:0], 1'b0};
					else
						temp_div_result <= {sub_result[31:0], temp_div_result[30:0], 1'b1};
					
					state <= `State_On;
					count <= count + 1;
				end
				
			endcase
endmodule